﻿using System;

namespace HappyTemplate
{
	public class SourceException : Exception
	{
		private readonly SourceLocation _location;
		readonly Enum _key;

		public SourceLocation Location { get { return _location; } }

		public Enum Key { get { return _key; } }


		public SourceException(SourceLocation loc)
		{
			_location = loc;
		}

		public SourceException(SourceLocation loc, string msg)
			: base(msg)
		{
			_location = loc;
		}

		public SourceException(Exception inner, SourceLocation loc, string msg)
			: base(msg, inner)
		{
			_location = loc;
		}

		public SourceException(SourceLocation loc, Enum key)
			: this(loc)
		{
			_key = key;
		}

		public SourceException(SourceLocation loc, Enum key, string msg)
			: this(loc, msg)
		{
			_key = key;
		}


		public SourceException(Exception inner, SourceLocation loc, Enum key, string msg)
			: this(inner, loc, msg)
		{
			_key = key;
		}

		public SourceException(SourceLocation loc, string msg, params object[] args)
			: this(loc, StringHelp.Format(msg, args))
		{
		}

		public SourceException(SourceLocation loc, Enum key, string msg, params object[] args)
			: this(loc, key, StringHelp.Format(msg, args))
		{
			
		}

		public SourceException(Exception inner, SourceLocation loc, Enum key, string msg, params object[] args)
			: this(inner, loc, key, StringHelp.Format(msg, args))
		{

		}

		public override string ToString()
		{
			return String.Format("{0}: {1}", _location, this.Message);
		}

	}

	public class AbortParseException : SourceException
	{
		public AbortParseException(SourceLocation loc)
			: base(loc)
		{

		}
	}

	public class InternalSourceException : SourceException
	{
		public InternalSourceException(SourceLocation loc)
			: base(loc) { }
		public InternalSourceException(SourceLocation loc, string msg, params object[] args)
			: base(loc, msg, args)  { }

		public InternalSourceException(SourceLocation loc, Exception inner, string msg, params object[] args)
			: base(loc, String.Format(msg, args), inner) { }
	}

	public class EofException : AbortParseException
	{
		public EofException(SourceLocation loc)
			: base(loc)
		{

		}
	}

	public class UnhandledCaseSourceException : InternalSourceException
	{
		public UnhandledCaseSourceException(SourceLocation loc)
			: base(loc)
		{
		}

		public UnhandledCaseSourceException(SourceLocation loc, string msg)
			: base(loc, msg)
		{
		}
	}


	public class BuiltInFunctionException : ApplicationException
	{
		public BuiltInFunctionException(string msg, params object[] args)
			: base(String.Format(msg, args)) { }

		public BuiltInFunctionException(Exception inner, string msg, params object[] args)
			: base (String.Format(msg, args), inner) {}
	}

	public class ArgumentConversionException : ApplicationException
	{
		private readonly int _argumentIndex;

		public ArgumentConversionException(int argumentIndex, Exception inner)
			: base(null, inner)
		{
			_argumentIndex = argumentIndex;
		}

		public int ArgumentIndex
		{
			get { return _argumentIndex; }
		}
	}
}
